pub struct Interpreter<'a> {
    iter: std::str::Chars<'a>,
}

impl<'a> Interpreter<'a> {
    pub fn new(infix: &'a str) -> Self {
        Self {
            iter: infix.chars(),
        }
    }

    fn next_char(&mut self) -> Option<char> {
        self.iter.next()
    }

    pub fn interpret(&mut self, output: &mut String) {
        self.term(output);

        while let Some(op) = self.next_char() {
            if op == '+' || op == '-' {
                self.term(output);
                output.push(op);
            } else {
                panic!("Unexpected symbol '{op}'");
            }
        }
    }

    fn term(&mut self, output: &mut String) {
        match self.next_char() {
            Some(ch) if ch.is_ascii_digit() => output.push(ch),
            Some(ch) => panic!("Unexpected symbol '{ch}'"),
            None => panic!("Unexpected end of string"),
        }
    }
}

fn main() {
    let mut interpreter = Interpreter::new("2+3");
    let mut postfix = String::new();
    interpreter.interpret(&mut postfix);
    assert_eq!("23+", postfix);

    interpreter = Interpreter::new("1-2+3-4");
    postfix.clear();
    interpreter.interpret(&mut postfix);
    assert_eq!("12-3+4-", postfix);
}
